package site.icesky.springboot.threadpool.util;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName: FtpUtil <br>
 * @Description: ftp工具类 <br>
 * @Package: site.icesky.springboot.threadpool.util <br>
 * @author: suitianmou <br>
 * @Date: 2020/8/15-11:41 <br>
 * @version: 1.0 <br>
 * @see <br>
 * @since (从产品的哪一个版本此类被添加进来 ( 可选))<br>
 * 修改历史: <br>
 * 修改时间             修改人           版本变更           修改说明<br>
 * -----------------------------------------------------<br>
 * <br>
 */
//jdk1.7之后的自动关闭接口,和finally

public class FtpUtil implements AutoCloseable {

    private FTPClient ftpClient;
    private Logger logger = LoggerFactory.getLogger(FtpUtil.class);
    // ls命令可展示的最大文件列表数量
    private static final int FTPMAXFILELISTNUM = 100000;

    /**
     * @Title: connectServer  <br>
     * @Description: desc  <br>
     * @version: 1.0  <br>
     * @param: [ip, port, userName, password, passiveMode]  <br>
     * @return: void  <br>
     * @author: suitianmou  <br>
     * @Date: 2020/8/16-21:15  <br>
     * history:  <br>
     * 修改记录：  修改人           版本变更           修改说明<br>
     * -----------------------------------------------------<br>
     * <br>
     */
    public boolean connectServer(String ip, int port, String userName, String password, boolean passiveMode) {

        ftpClient = new FTPClient();
        // 连接
        try {
            ftpClient.connect(ip, port);
            // 登录
            ftpClient.login(userName, password);
            // 设置bin二进制模式
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

        } catch (IOException e) {
            logger.error("基本连接信息:IP{},PORT{},USERNAME{},PASSWORD{}", ip, port, userName, password);
            logger.error("连接异常!!!", e);
            return false;
        }

        // 是否启用被动模式
        if (passiveMode == true) {
            ftpClient.enterLocalPassiveMode();
        }

        // 设置超时参数
        ftpClient.setBufferSize(1024);
        ftpClient.setControlEncoding("UTF-8");

        // 设置超时时间
        ftpClient.setDefaultTimeout(60 * 1000);
        ftpClient.setConnectTimeout(10 * 1000);
        ftpClient.setDataTimeout(60 * 1000);

        return true;
    }

    //对应 ftp的get命令，获取文件到本地
    public boolean get(String remotePath, String fileName, String localPath) {

        // 先判断ftp是否连接
        if (ftpClient == null) {
            logger.error("ftpClient未连接和初始化!!!");
            return false;
        }

        String localFileName = localPath + fileName;

        // 打开本地文件
        File outPutFile = new File(localFileName);
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(outPutFile);
        } catch (FileNotFoundException e) {
            logger.error("打开本地文件异常!", e);
            return false;
        }

        // 从远程读取文件到本地的文件流中
        String remoteFileName = remotePath + fileName;
        try {
            ftpClient.retrieveFile(remoteFileName, outputStream);
        } catch (IOException e) {
            logger.error("获取远程文件异常", e);
            return false;
        }

        return true;
    }

    //对应 ftp的put命令，将本地文件上传到远程
    public boolean put(String remotePath, String fileName, String localPath) {
        String localFile = localPath + fileName;

        // 打开文件流
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(localFile);
        } catch (FileNotFoundException e) {
            logger.error("打开本地文件异常!", e);
            return false;
        }
        if (ftpClient == null) {
            logger.error("ftpClient未连接和初始化!!!");
            return false;
        }
        // 上传
        try {
            ftpClient.makeDirectory(remotePath);
            ftpClient.changeWorkingDirectory(remotePath);
            ftpClient.storeFile(fileName, inputStream);
        } catch (IOException e) {
            logger.error("上传文件到服务器异常!", e);
            return false;
        }

        return true;
    }

    // 远程切换文件夹
    public boolean cd(String remotePath) {
        try {
            ftpClient.changeWorkingDirectory(remotePath);
        } catch (IOException e) {
            logger.error("切换目录失败-{}", remotePath);
            logger.error("异常:", e);
            return false;
        }
        return true;
    }

    // 远程创建文件夹
    public boolean mkdir(String remotePath) {
        try {
            ftpClient.makeDirectory(remotePath);
        } catch (IOException e) {
            logger.error("创建目录失败-{}", remotePath);
            logger.error("异常:", e);
            return false;
        }
        return true;
    }

    // 将远程文件列表展示出来
    public List<String> ls(String remotePath) {

        List<String> fileList = new ArrayList<>();

        try {
            FTPFile[] files = ftpClient.listFiles(remotePath);
            int i = 0;
            for (FTPFile f : files) {
                i++;
                if( f.isDirectory()){
                    fileList.add(f.getName() + "/");
                }
                else{
                    fileList.add(f.getName());
                }

                if( i > FTPMAXFILELISTNUM ){
                    logger.error("远程文件数量过多,超过上限，请检查-{}", i);
                    return null;
                }

                logger.debug("[{}] {} {} {} {}",i,  f.getName(), f.getSize(), f.getTimestamp().getTime(), f.getUser());
            }
        } catch (IOException e) {
            logger.error("远程文件列表刷新失败-{}", remotePath);
            logger.error("异常:", e);
            return null;
        }

        return fileList;
    }

    // 实现关闭方法，AutoCloseable接口要求
    @Override
    public void close() throws IOException {
        if (ftpClient != null && ftpClient.isConnected()) {

            ftpClient.logout();
            ftpClient.disconnect();
        }
    }
}
